from calc_manager.file import FileInfo, FileOperatorHelper
from calc_manager.operator.operator import OperatorInfo
from calc_manager.operator.repo import OperatorRepository
from calc_manager.algorithm.repo import AlgorithmRepository
from calc_manager.algorithm.algo import AlgorithmInfo
from calc_manager.res_helper import ResourceHelper
from typing import Optional
import logging

logger = logging.getLogger(__name__)


class ShDcOperatorRepository(OperatorRepository):
    # if no operator_working_dir_path set in the constructor, it will use relative path
    def __init__(self, uri, operator_working_dir_path = None):
        self.operator_working_dir_path = operator_working_dir_path
        self.res_helper = ResourceHelper(uri)

    def get_operator_info_by_raw(self, opinfo_raw: dict, op_id: str) -> OperatorInfo:
        working_dir = self.operator_working_dir_path if self.operator_working_dir_path else None
        info = {
            "operator_id": op_id,
            "operator_name": opinfo_raw["nameEn"],
            "operator_path": opinfo_raw["operator_path"],
            "operator_func_entrypoint": opinfo_raw["entryFunc"],
            "operator_workingdir": working_dir
        }
        opinfo = OperatorInfo(**info)
        logger.info("get operator from ShDcRes Repo: %s", opinfo)
        return opinfo

    def get_op_by_id(self, op_id: str) -> Optional[OperatorInfo]:
        try:
            opinfo_raw = self.res_helper.get_operator_info(op_id)
            op_file_path = opinfo_raw["operatorUrl"]
            file_path = self.res_helper.get_file_signature(op_file_path)
            file_helper = FileOperatorHelper(FileInfo(file_path, opinfo_raw))
            extract_path = file_helper.download_and_extract()
            logger.info(extract_path)
            opinfo_raw["operator_path"] = extract_path + "/" + opinfo_raw["entryFilePath"]
            return self.get_operator_info_by_raw(opinfo_raw, op_id)
        except Exception as e:
            raise Exception("Failed to get operator by id: %s, err:%s" % (op_id, e) ) from e

class ShDcAlgoRepository(AlgorithmRepository):
    # if no operator_working_dir_path set in the constructor, it will use relative path
    def __init__(self, uri):
        self.res_helper = ResourceHelper(uri)

    def get_algo_by_id(self, algo_id: str) -> Optional[AlgorithmInfo]:
        try:
            algo_raw = self.res_helper.get_algo_info(algo_id)
            return AlgorithmInfo(algo_name=algo_raw["nameEn"],
                          algo_desc=algo_raw["name"],
                          graph_json=algo_raw["algoSchema"])
        except Exception as e:
            raise Exception("Failed to get operator by id: %s, err:%s" % (algo_id, e) ) from e
